package com.uw.tookit;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.LinearLayout;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.uw.tookit.MyLocation.LocationResult;

/**
 * This class represents the getting directions activity.
 * It should be directed from info page "Get Directions" button and will show the walking route between user-defined
 * destinations.
 */
public class GetPath extends MapActivity {
    
    LinearLayout linearLayout;
    MapView mapView;
    private Road mRoad;
    MyLocation myLocation = new MyLocation();
    MapController mc;
    private boolean getCurLocFlag = false;
    private double fromLat;
    private double fromLon;
    private double toLat;
    private double toLon;
    private String name = "";
    private boolean hasLocation = false;

	/**
	 * Called when the activity is first created.
	 * Get path on the map.
	 */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.map);
        mapView = (MapView) findViewById(R.id.mapView);
        mapView.setBuiltInZoomControls(true);
        mc = mapView.getController();
        
        // Check if any extras exist.
        Bundle extras = getIntent().getExtras();
		if(extras != null) {
			//Directed from info page "Get directions" button.
			toLat = extras.getDouble("lat");
			toLon = extras.getDouble("lon");
        	name = extras.getString("name");
			
			// Get current latitude and longitude;
			// If GPS and network service disabled on phone, notify the user.
        	hasLocation=false;
            if(!myLocation.getLocation(this, currlocationResult)) {
            	AlertDialog alertDialog = new AlertDialog.Builder(GetPath.this).create();
	            alertDialog.setMessage("GPS and network services are not enabled on your phone. Enable them and try again.");
	      	  	alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
	      	  		public void onClick(DialogInterface dialog, int which) {
	      	  			return;
	      	    } });
        	    alertDialog.show();
            } else {        	  
            	// If current location found, find directions between it and the destination.	
            	new Thread() {
		            @Override
		           public void run() {
		            	int count = 0;
		            	// try to find current location;
		            	// timeout in 5 seconds.
		                while(!hasLocation && count <= 10){
		                	try {
								Thread.sleep(500); // sleep for 0.5 sec
							} catch (InterruptedException e) {
							}
		                	count++;
		                }
		                // If timeout, alert the user.
		                if(!hasLocation) {
		                	mHandler.post(new Runnable() {
		                		public void run() {
		                			AlertDialog alertDialog = new AlertDialog.Builder(GetPath.this).create();
		                			alertDialog.setMessage("We can't find you right now. Try again later.");
		                			alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
		                				public void onClick(DialogInterface dialog, int which) {return;} 
		                			});
		                			alertDialog.show();
		                		}});
		                } else {
		                	// If current location found, get directions to the destination.
			                String url = RoadProvider.getUrl(fromLat, fromLon, toLat, toLon);
			                InputStream is = getConnection(url);
			                mRoad = RoadProvider.getRoute(is);
			                mHandler.sendEmptyMessage(0);
		                }
		            }
		        }.start();
            }
		}
    }
    
    /**
     * Draw the route on the map and mark the starting and ending point.
     */
    Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
        	GeoPoint start = new GeoPoint((int) (fromLat * 1E6), (int) (fromLon * 1E6));
        	GeoPoint end = new GeoPoint((int) (toLat * 1E6), (int) (toLon * 1E6));
        	PathOverlay mapOverlay = new PathOverlay(mRoad, mapView);
        	PinOverlay s = new PinOverlay(GetPath.this, start, R.drawable.pawpin, "Start");
        	PinOverlay e = new PinOverlay(GetPath.this, end, R.drawable.pawpin, name);
            List<Overlay> listOfOverlays = mapView.getOverlays();
            listOfOverlays.clear();
            listOfOverlays.add(mapOverlay);
            listOfOverlays.add(s);
            listOfOverlays.add(e);
            mapView.invalidate();
        };
    };
    
    /**
     * Connects to the google map for searching.
     * @param url the URL to go.
     */
    private InputStream getConnection(String url) {
        InputStream is = null;
        try {
            URLConnection conn = new URL(url).openConnection();
            is = conn.getInputStream();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return is;
    }
    
    /**
     * Does not display any route.
     */
    @Override
    protected boolean isRouteDisplayed() {
        return false;
    }
    
    /**
     * Create the options menu when load the map.
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.mapmenu, menu);
        return true;
    }
    
    /**
     * Get current location.
     */
    LocationResult currlocationResult = new LocationResult(){
	    @Override
	    public void gotLocation(final Location loc){
	    	if(loc != null) {
		    	// Get the current location.
	        	fromLat = loc.getLatitude();
	        	fromLon = loc.getLongitude();
	        	hasLocation = true;
	    	}
	    }
	};
    
    /**
     * Handle the event when a menu item is selected.
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle item selection.
        switch (item.getItemId()) {
            case R.id.gps_button:
            	// If GPS service disabled on phone, notify the user.
                if(!myLocation.getLocation(this, currlocationResult)) {
                	AlertDialog alertDialog = new AlertDialog.Builder(GetPath.this).create();
		            alertDialog.setMessage("GPS and network services are not enabled on your phone. Enable them and try again.");
		      	  	alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
		      	  		public void onClick(DialogInterface dialog, int which) {
		      	  			return;
		      	    } });
	        	  alertDialog.show();
                } else {
                	int count = 0;
	            	// try to find current location;
	            	// timeout in 5 seconds.
	                while(!hasLocation && count <= 10){
	                	try {
							Thread.sleep(500); // sleep for 0.5 sec
						} catch (InterruptedException e) {
						}
	                	count++;
	                }
	                // If timeout, alert the user.
	                if(!hasLocation) {
	                	mHandler.post(new Runnable() {
	                		public void run() {
	                			AlertDialog alertDialog = new AlertDialog.Builder(GetPath.this).create();
	                			alertDialog.setMessage("We can't find you right now. Try again later.");
	                			alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
	                				public void onClick(DialogInterface dialog, int which) {return;} 
	                			});
	                			alertDialog.show();
	                		}});
	                } else {
	                	// If current location found, mark it on the map.
	                	GeoPoint p = new GeoPoint((int) (fromLat * 1E6), (int) (fromLon * 1E6));
					    mc.animateTo(p);
					    
				        //---Add a location marker---
				        PinOverlay mo = new PinOverlay(GetPath.this, p, R.drawable.pawpin, "You are here");
				        List<Overlay> listOfOverlays = mapView.getOverlays();
				        if(getCurLocFlag)
				        	listOfOverlays.remove(listOfOverlays.size()-1);
				        listOfOverlays.add(mo);
				        getCurLocFlag = true;
				        mc.setZoom(18);
				        mapView.invalidate();
	                }
                }
                return true;
            case R.id.mainpage_button:
            	Intent resultsPage = new Intent(GetPath.this, UWToolkitActivity.class);
                startActivityForResult(resultsPage, 0);
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
}

